package com.jsy.common.util.bytecode;

import org.objectweb.asm.*;

import java.io.*;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;

/**
 * ASM示例：修改Jar文件中的类
 */
public class ModifyJarClassExampleASM {
    public static void main(String[] args) throws IOException {
        String inputJarPath = "yourjarfile.jar";
        String outputJarPath = "yournewjarfile.jar";

        try (JarFile jarFile = new JarFile(inputJarPath);
             JarOutputStream jos = new JarOutputStream(new FileOutputStream(outputJarPath))) {

            Enumeration<JarEntry> entries = jarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry entry = entries.nextElement();
                jos.putNextEntry(new JarEntry(entry.getName()));

                if (entry.getName().endsWith(".class")) {
                    try (InputStream is = jarFile.getInputStream(entry)) {
                        ClassReader cr = new ClassReader(is);
                        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
                        ClassVisitor cv = new MyClassVisitor(Opcodes.ASM9, cw);
                        cr.accept(cv, 0);
                        byte[] modifiedClassBytes = cw.toByteArray();
                        jos.write(modifiedClassBytes);
                    }
                } else {
                    try (InputStream is = jarFile.getInputStream(entry)) {
                        byte[] buffer = new byte[1024];
                        int bytesRead;
                        while ((bytesRead = is.read(buffer)) != -1) {
                            jos.write(buffer, 0, bytesRead);
                        }
                    }
                }
                jos.closeEntry();
            }
        }
    }

    static class MyClassVisitor extends ClassVisitor {
        public MyClassVisitor(int api, ClassVisitor cv) {
            super(api, cv);
        }

        @Override
        public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
            MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
            // 在这里可以对方法进行修改
            if (name.equals("methodName")) {
                // 返回null表示删除该方法
                mv = null;
            }
            // 修改方法名为"oldMethod",返回true
            if ("oldMethod".equals(name)) {
                return new MethodVisitor(Opcodes.ASM9, mv) {
                    @Override
                    public void visitCode() {
                        // 新方法体：直接返回true
                        mv.visitInsn(Opcodes.ICONST_1);
                        // 返回false
//                        mv.visitInsn(Opcodes.ICONST_0);
                        mv.visitInsn(Opcodes.IRETURN);
                    }
                    @Override
                    public void visitMaxs(int maxStack, int maxLocals) {
                        // 重新设置最大栈和最大局部变量数
                        mv.visitMaxs(1, 0);
                    }
                };
            }
            return mv;
        }
    }
}    